package gui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumn;

import skyproc.SPGlobal;
import edit.GRUPHolder;
import edit.SPDatabaseHolder;
import edit.jTES5Edit;


@SuppressWarnings("serial")
public class GUI extends JComponent {
	
	private JFrame mainFrame;
	private JSplitPane splitPane;
	private ModTreeTablePanel treeTable;
	private ModTreeTablePanel recordInformation;
	private JTextField formID_f;
	private JTextField editID_f;
	private JTextField name_f;
	private JPopupMenu popup;
	
	// Filtering stuff
	private       JComponent currentFilter = null;
	
	public GUI() {
		
		 ////////////////////////////////////
		// 1. Create the components.
		JLabel     formID_l = new JLabel("FormID");
		JLabel     editID_l = new JLabel("EditorID");
		JLabel     name_l   = new JLabel("Name");
		formID_f = new JTextField(8);
		editID_f = new JTextField(30);
		name_f   = new JTextField(30);
		
		recordInformation = new ModTreeTablePanel(new RecordInformationTableModel(null));
		JTextArea help = new JTextArea();
		JScrollPane helpScroller = new JScrollPane(help);
		/////////////////////////////////////
		
		 /////////////////////////////////////////////
		// 2. Set the properties of the components.
		JScrollPane recordInfoHolder = new JScrollPane(recordInformation);
		treeTable = new ModTreeTablePanel(new TreeTableModModel(new SPDatabaseHolder(SPGlobal.getDB())));
		treeTable.getTreeTable().getAdapter().addRecordSelectedListener();
		treeTable.getTreeTable().getAdapter().addObserver( recordInformation.getTreeTable() );
		//////////////////////////////////////////////
		

		 //////////////////////////////////////////////////
		// 3. Create containers to hold the components.
		
		// leftPanel
		JPanel leftPanel = new JPanel();
		
		// Sort panel stuff
		JPanel filterPanel = new JPanel();
		
		mainFrame = new JFrame("jTES5Edit");
		splitPane = new JSplitPane();
		JTabbedPane tabs = new JTabbedPane();
		///////////////////////////////////////////////////
		
		 /////////////////////////////////////////////////////////////////////
		// 4. Specify the arrangement of components using a LayoutManager.
		mainFrame.setLayout(new BorderLayout());
		tabs.setTabPlacement(JTabbedPane.BOTTOM);
		
		// Filter panel
		filterPanel.setLayout( new FlowLayout() );
		
		// leftPanel
		leftPanel.setLayout(new BoxLayout(leftPanel, BoxLayout.Y_AXIS));
		//////////////////////////////////////////////////////////////////////
		
		 /////////////////////////////////////
		// 5. Add components to containers.
		
		// filterPanel
		filterPanel.add(formID_l);
		filterPanel.add(formID_f);
		filterPanel.add(editID_l);
		filterPanel.add(editID_f);
		filterPanel.add(name_l);
		filterPanel.add(name_f);
		filterPanel.setBorder( BorderFactory.createTitledBorder("Filter") );
		
		// leftPanel
		leftPanel.add(filterPanel);
		leftPanel.add(treeTable);
		
		// tabs
		tabs.add(recordInfoHolder, "View");
		tabs.add(helpScroller, "Help");
		
		// splitPane
		splitPane.setLeftComponent(leftPanel);
		splitPane.setRightComponent(tabs);
		
		// mainFrame
		mainFrame.add(splitPane, BorderLayout.CENTER);
		
		//popup
		createPopupMenu();
		//////////////////////////////////////
		
		
		 /////////////////////////////////////
		// 6. Organise the event handling.
		mainFrame.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e) {
				System.exit(0);
			}
		});
		
		treeTable.getTreeTable().setComponentPopupMenu(this.popup);
		
		treeTable.getTreeTable().getTableHeader().addMouseListener( new MouseAdapter() {
			public void mouseClicked(MouseEvent e) {
				sortByColumn(e);
			}
		});
		
		formID_f.addKeyListener( new KeyListener() {
			@Override
			public void keyPressed(KeyEvent e) {
				filter( e, "FormID", formID_f.getText().trim() );
			}
			@Override
			public void keyReleased(KeyEvent e){/*Do nothing*/}
			@Override
			public void keyTyped(KeyEvent e)   {/*Do nothing*/}
			
		});
		editID_f.addKeyListener( new KeyListener() {
			@Override
			public void keyPressed(KeyEvent e) {
				filter( e, "EditorID", editID_f.getText().trim() );
			}
			@Override
			public void keyReleased(KeyEvent e){/*Do nothing*/}
			@Override
			public void keyTyped(KeyEvent e)   {/*Do nothing*/}
		});
		
		name_f.addKeyListener( new KeyListener() {
			@Override
			public void keyPressed(KeyEvent e) {
				filter( e, "Name", name_f.getText().trim() );
			}
			@Override
			public void keyReleased(KeyEvent e){/*Do nothing*/}
			@Override
			public void keyTyped(KeyEvent e)   {/*Do nothing*/}
		});
		//////////////////////////////////////
		
		
		 //////////////////////////
		// 7. Display the GUI.
		mainFrame.setExtendedState(JFrame.MAXIMIZED_BOTH);
		mainFrame.pack();
		mainFrame.setVisible(true);	
		mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		///////////////////////////
	}
	
	private void filter(KeyEvent e, String column, String filt) {
		if(e.getKeyCode() == KeyEvent.VK_ENTER)
		{
			// Set filters
			if( column.equals("FormID") ) {
				GRUPHolder.fType = GRUPHolder.FilterType.FORM;
			}
			else if( column.equals("EditorID") ) {
				GRUPHolder.fType = GRUPHolder.FilterType.EDID;
			}
			else if( column.equals("Name") ) {
				GRUPHolder.fType = GRUPHolder.FilterType.NAME;
			}
			else {
				GRUPHolder.fType = GRUPHolder.FilterType.NONE;
			}
			GRUPHolder.filter     = filt;
			
			// Set background colours
			if(currentFilter != null)
				currentFilter.setBackground(Color.WHITE);
			((JComponent)e.getSource()).setBackground( Color.GREEN );
			
			// Update current filter
			currentFilter = (JComponent)e.getSource();
			
			// Refresh
			refreshTreeTable();
		}
	}
	
	private void sortByColumn(MouseEvent e) {
		JTableHeader src = (JTableHeader) e.getSource();
		int columnIndex = src.columnAtPoint( e.getPoint() );
		
		// Set column
		TableColumn column = src.getColumnModel().getColumn(columnIndex);
		
		Object columnHeader = column.getHeaderValue();
		
		if( columnHeader.toString().equals("FormID") ) {
			GRUPHolder.sType = GRUPHolder.SortType.FORM;
		}
		else if( columnHeader.toString().equals("EditorID") ) {
			GRUPHolder.sType = GRUPHolder.SortType.EDID;
		}
		else if( columnHeader.toString().equals("Name") ) {
			GRUPHolder.sType = GRUPHolder.SortType.NAME;
		}
		
		// Refresh
		refreshTreeTable();
	}
	
	/**
	 * Creates the popup menu used by the checkboxes.
	 */
	private void createPopupMenu() {
		JMenuItem menuItem;

		this.popup = new JPopupMenu();
		menuItem = new JMenuItem("Remove ITMs");
		menuItem.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e){
				jTES5Edit.removeITMs();
				refreshTreeTable();
			}
		});		
		this.popup.add(menuItem);
	}
	
	private void refreshTreeTable() {
		
		// Had to change the visibility of JTreeTable.setUp() to package private. 
		// I'm not familiar enough with TreeTables to isolate exactly what causes
		// it to refresh. If you know, go right ahead and modify accordingly :)
		treeTable.getTreeTable().setUp( treeTable.getTreeTable().getAdapter().getTreeTableModel() );
		
		treeTable.getTreeTable().getAdapter().addRecordSelectedListener();
		treeTable.getTreeTable().getAdapter().addObserver(recordInformation.getTreeTable());
	}
}
